home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-04-06 | 25.3 KB | 658 lines | [TEXT/CCL2] |
- ;;;
- ;;; sound-fun.Lisp
- ;;;
-
- #|
- ================================================================
- Purpose ========================================================
- ================================================================
-
- Contains code for experimenting with the extended sound manager's square
- wave, wave table, and sampled sounds synthesizers. Defines the sound-dialog
- dialog subclass that has a sound associated with each of its four buttons.
- Also, pressing one of the keys 1-4 will play the corresponding button's
- sound.
-
- To try the example out: Evaluate this file then evaluate
- (make-instance 'sound-dialog) .
-
-
- To use a particular synthesizer: Which synth is used is determined in
- play-button-snd; the default is the wave table synth. The wave table is
- specified in sound-dialog's initialize-instance :after method. If you want
- to use the square wave synth change play-button-snd to pass :square-wave? t
- to play-note. If you want to use the sampled sound synth uncomment the two
- forms in play-button-snd and comment-out the others, and uncomment the two
- resource-related forms at this file's top. You will need to substitute for
- "ccl:HAT;Resources;emits.rsrc" the name of a suitable file that contains sampled
- 'snd 's, and you will need my "resource utils.lisp" file which should be
- available where you found this file.
-
-
- Background: I wrote this file to test the Sound Manager's performance in
- playing sampled sounds to evaluate using it as a drum machine. My first
- version simply called SndPlay using the appropriate handle. This was
- unacceptable because the response was too slow and the sounds were played
- synchronously so we need to stop and restart a sound if it's playing when
- its key is hit. This means we must explicitly pass a channel to SndPlay so
- we can stop the previous sound and restart it. So I now keep four
- SndChannel records in the window which are allocated and deallocated via
- #_SndNewChannel and #_SndDisposeChannel. To do asynchronous sounds and to
- stop currently-playing sounds I use the SndChannel's userInfo field with
- these values (states): *released*, *quietNotReleased*, and *playing*. (See the
- constants' definitions for their semantics.) But alas the thing is still
- too slow (and it's not MCL's fault!). Yet this file does show how to use
- the various synths.
-
- Copyright © 1990-92 Matthew Cornell. All Rights Reserved. Send
- bugs, comments, questions, and fixes to cornell@cs.umass.edu.
-
-
- ================================================================
- Status =========================================================
- ================================================================
- Implemented.
-
-
- ================================================================
- Change history =================================================
- ================================================================
- 20-Aug-91 mc Created.
- 21-Aug-91 mc Changed to using a dialog.
- 24-Aug-91 mc Get "pre-emptive" sound production working. Still unresponsive…
- 2-Oct-91 mc Added functions to use the #$squareWaveSynth. Result: couldn't
- play more than one note at a time. So:
- 2-Oct-91 mc Added functions for #$waveTableSynth.
- 18-Oct-91 mc Added further comments for release.
- 14-Mar-92 mc Put into cl-user package.
- 6-Apr-92 mc Changed names of *released*, *quietNotReleased*, and *playing* .
- Changed $var to #$var to eliminate warnings and errors.
- Changed sample resource file and resource names.
- Changed #\3 in view-key-event-handler to #\5 .
-
- |#
-
- (in-package "CL-USER")
-
- (ccl::require-interface "SOUND")
-
-
- #| ;;; Open the resource file that contains the needed sounds.
-
- (require "resource-utils" "ccl:UMASS Utils;resource-utils")
- (open-resource-file "ccl:HAT;Resources;emits.rsrc")
-
- |#
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Define the constants.
- ;;;
-
- (defconstant *quietNotReleased* #x0
- "Means the channel is not playing but has NOT been released. Set by the
- callback routine.")
-
- (defconstant *released* #x1
- "Means the channel is not playing and HAS been released.")
-
- (defconstant *playing* #x2
- "Means the channel is currently playing a sound.")
-
-
- (defmethod state-number->name ((state-number fixnum))
- "Returns the symbol corresponding to STATE-NUMBER or errors."
- ;;
- (cond ((= state-number *quietNotReleased*)
- '*quietNotReleased*)
- ((= state-number *released*)
- '*released*)
- ((= state-number *playing*)
- '*playing*)
- (t (error "~S is not one of these known states: ~S."
- state-number (list *released* *quietNotReleased* *playing*)))))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Define the callback routine. The following is:
- ;;
- ;; Copyright © 1990 Northwestern University Institute for the Learning Sciences
- ;; All Rights Reserved
- ;;
- ;; author: Michael S. Engber
- ;;
- ;;;
- ;;; Since the call back routine is called at interrupt time, there are several
- ;;; restrictions on it (see Sound Manager chapter of IM) which MACL's defpascal
- ;;; mechanism does not obey. So it was written in C. The compiled code is small
- ;;; enough that we can just copy its machine code into memory when a sound channel
- ;;; is created (avoiding loading CODE resources or external function calls)
- ;;;
- ;;; #include <SoundMgr.h>
- ;;;
- ;;; pascal void main (SndChannelPtr theChan, SndCommand* theCmd){
- ;;; theChan->userInfo = 0L;
- ;;; }
- ;;;
- ;;;
-
- (defvar *snd-call-back-mcode* "600E0000434F444501F400000000000041FAFFEE4E714E71600000024E560000206E000C42A8000C4E5E205F4FEF00084ED04D41494E20202020"
- "The machine code (hex) for call back routine.")
-
-
- (defvar *snd-call-back-ptr* nil "The pointer to call back routine.")
-
-
- (defun stuff-call-back-ptr ()
- "Stuffs machine code for call back routine into memory."
- ;;
- (when *snd-call-back-ptr*
- (dispose-of-call-back-ptr))
- (setf *snd-call-back-ptr* (#_NewPtr (/ (length *snd-call-back-mcode*) 2)))
- (with-pstrs ((p *snd-call-back-mcode*))
- (#_StuffHex *snd-call-back-ptr* p)))
-
- (stuff-call-back-ptr)
-
-
- (defun dispose-of-call-back-ptr ()
- (when *snd-call-back-ptr*
- (#_DisposPtr *snd-call-back-ptr*)
- (setf *snd-call-back-ptr* nil)))
-
- (pushnew #'dispose-of-call-back-ptr *lisp-cleanup-functions*
- :test #'eq :key #'function-name) ;function-name is a ccl function
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Define the sound-dialog class and methods.
- ;;;
- ;;; The item's text strings are the 'snd ' resource names. The sounds are
- ;;; activated by either pressing the button with the mouse or hitting the
- ;;; appropriate character. The keys are the keypad keys 1, 2, 4, and 5
- ;;; arranged like the buttons are: #\4 #\5
- ;;;
- ;;; #\1 #\2
- ;;;
- ;;; Sound playing protocol: You specify which sound to play by passing to
- ;;; my-play-sound the nickname (symbol) of the corresponding button which
- ;;; plays that sound.
- ;;;
-
- (defclass sound-dialog (dialog)
- (;; The following four channel slots hold SndChannel records. The are
- ;; deallocated by window-close.
- (channel1
- :accessor channel1
- :type macptr)
- (channel2
- :accessor channel2
- :type macptr)
- (channel3
- :accessor channel3
- :type macptr)
- (channel4
- :accessor channel4
- :type macptr)
- ;;
- (int-table-length
- :accessor int-table-length :type fixnum
- :documentation "The wave table's length in bytes.")
- (ptr-table-data
- :accessor ptr-table-data :type fixnum
- :documentation "The wave table's data.")
- )
- (:default-initargs
- :WINDOW-TYPE :TOOL :VIEW-POSITION '(:TOP 111)
- :VIEW-SIZE #@(194 59) :VIEW-FONT '("Chicago" 12 :SRCOR :PLAIN)
- :VIEW-SUBVIEWS
- (LIST (MAKE-DIALOG-ITEM 'BUTTON-DIALOG-ITEM
- #@(4 31)
- #@(84 16)
- "Got an IV started"
- #'(lambda (item)
- (play-button-snd (view-container item)
- 'BOTTOM-LEFT-ITEM))
- :VIEW-NICK-NAME 'BOTTOM-LEFT-ITEM
- :DEFAULT-BUTTON NIL)
- (MAKE-DIALOG-ITEM 'BUTTON-DIALOG-ITEM
- #@(97 31)
- #@(84 16)
- "Trouble with the IV"
- #'(lambda (item)
- (play-button-snd (view-container item)
- 'BOTTOM-RIGHT-ITEM))
- :VIEW-NICK-NAME 'BOTTOM-RIGHT-ITEM
- :DEFAULT-BUTTON NIL)
- (MAKE-DIALOG-ITEM 'BUTTON-DIALOG-ITEM
- #@(4 4)
- #@(84 16)
- "Got The Tube In"
- #'(lambda (item)
- (play-button-snd (view-container item)
- 'TOP-LEFT-ITEM))
- :VIEW-NICK-NAME 'TOP-LEFT-ITEM
- :DEFAULT-BUTTON NIL)
- (MAKE-DIALOG-ITEM 'BUTTON-DIALOG-ITEM
- #@(97 4)
- #@(84 16)
- "Trouble with the Tube"
- #'(lambda (item)
- (play-button-snd (view-container item)
- 'TOP-RIGHT-ITEM))
- :VIEW-NICK-NAME 'TOP-RIGHT-ITEM
- :DEFAULT-BUTTON NIL)))
- (:documentation "A class of window that plays sounds when you press the
- top row's number keys. The character/sound-alist slot determines which
- characters play which sounds."))
-
-
- (defmethod initialize-instance :after ((object sound-dialog)
- &key)
- "Allocates and initializes the sound channels and the wave table."
- ;;
- ;; Save new SndChannel records in OBJECT's slots and set each channel's
- ;; userInfo field to *released* and each qLength field to #$stdQLength.
- ;;
- (setf (channel1 object) (make-record :SndChannel :qLength #$stdQLength)
- (channel2 object) (make-record :SndChannel :qLength #$stdQLength)
- (channel3 object) (make-record :SndChannel :qLength #$stdQLength)
- (channel4 object) (make-record :SndChannel :qLength #$stdQLength))
- (rset (channel1 object) SndChannel.userInfo *released*)
- (rset (channel2 object) SndChannel.userInfo *released*)
- (rset (channel3 object) SndChannel.userInfo *released*)
- (rset (channel4 object) SndChannel.userInfo *released*)
- ;;
- ;; Allocate the wave table and install triangle wave data.
- ;;
- (setf (int-table-length object) 512
- (ptr-table-data object) (#_NewPtr (int-table-length object)))
- #|
- ;; Install a triangle wave:
- (let ((int-slope (/ (- #xFF #x80) (int-table-length object)))
- (int-offset #x80))
- (labels ((int-index->data-value (int-index)
- "Returns the data value for int-index corresponding to a line
- from (0, #x80) to (512, #xFF)."
- ;;
- (round (+ (* int-slope int-index) int-offset))))
- (dotimes (int-index (int-table-length object))
- (%put-byte (ptr-table-data object) (int-index->data-value int-index)
- int-index))))
- |#
- ;; Install a square wave:
- (progn (loop for int-index from 0 to (round (int-table-length object) 2) do
- (%put-byte (ptr-table-data object) #xFF int-index))
- (loop for int-index from (1+ (round (int-table-length object) 2))
- to (1- (int-table-length object)) do
- (%put-byte (ptr-table-data object) #x00 int-index))))
-
-
- (defmethod window-null-event-handler ((window sound-dialog))
- "Releases any channels that are in the *quietNotReleased* state."
- ;;
- (when (and (slot-boundp window 'channel1) ;in case we're not fully
- (slot-boundp window 'channel2) ; initialized
- (slot-boundp window 'channel3)
- (slot-boundp window 'channel4))
- (release-channel-if-*quietNotReleased* (channel1 window))
- (release-channel-if-*quietNotReleased* (channel2 window))
- (release-channel-if-*quietNotReleased* (channel3 window))
- (release-channel-if-*quietNotReleased* (channel4 window))))
-
-
- (defmethod window-close :after ((view sound-dialog))
- "Calls quiet&release-channel, deallocates VIEW's four sound channels, and
- deallocates the wave table data."
- ;;
- (quiet&release-channel (channel1 view))
- (quiet&release-channel (channel2 view))
- (quiet&release-channel (channel3 view))
- (quiet&release-channel (channel4 view))
- (dispose-record (channel1 view))
- (dispose-record (channel2 view))
- (dispose-record (channel3 view))
- (dispose-record (channel4 view))
- ;;
- (#_DisposePtr (ptr-table-data view)))
-
-
- (defmethod view-key-event-handler ((view sound-dialog)
- (char character))
- "Handles the case of characters not handled below by doing nothing."
- ;;
- nil)
-
-
- (defmethod view-key-event-handler ((view sound-dialog)
- (char (eql #\4)))
- (play-button-snd view 'TOP-LEFT-ITEM))
-
-
- (defmethod view-key-event-handler ((view sound-dialog)
- (char (eql #\3)))
- (play-button-snd view 'TOP-RIGHT-ITEM))
-
-
- (defmethod view-key-event-handler ((view sound-dialog)
- (char (eql #\1)))
- (play-button-snd view 'BOTTOM-LEFT-ITEM))
-
-
- (defmethod view-key-event-handler ((view sound-dialog)
- (char (eql #\2)))
- (play-button-snd view 'BOTTOM-RIGHT-ITEM))
-
-
- ;;;
-
-
- (defmethod nick-name->channel ((view sound-dialog)
- (button-nick-name (eql 'BOTTOM-LEFT-ITEM)))
- (channel1 view))
-
-
- (defmethod nick-name->channel ((view sound-dialog)
- (button-nick-name (eql 'BOTTOM-RIGHT-ITEM)))
- (channel2 view))
-
-
- (defmethod nick-name->channel ((view sound-dialog)
- (button-nick-name (eql 'TOP-LEFT-ITEM)))
- (channel3 view))
-
-
- (defmethod nick-name->channel ((view sound-dialog)
- (button-nick-name (eql 'TOP-RIGHT-ITEM)))
- (channel4 view))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; LISP-level sound commands.
- ;;;
-
- (defmethod send-sound-command ((p-channel macptr)
- (cmd fixnum)
- (param1 fixnum)
- (param2 fixnum)
- &key (immediate? nil))
- "Sends CMD, PARAM1, and PARAM2 to P-CHANNEL via #_SndDoImmediate if
- IMMEDIATE? is non-nil, or via #_SndDoCommand."
- ;;
- (rlet ((p-command :SndCommand :cmd cmd :param1 param1 :param2 param2))
- (handle-error
- (if immediate?
- (#_SndDoImmediate p-channel p-command)
- (#_SndDoCommand p-channel p-command nil)))))
-
-
- (defmethod release-channel ((p-channel macptr))
- "Sets P-CHANNEL's userInfo field to *released* and calls
- #_SndDisposeChannel on P-CHANNEL."
- ;;
- (rset p-channel SndChannel.userInfo *released*)
- (handle-error (#_SndDisposeChannel p-channel nil)))
-
-
- (defmethod flush&quiet-p-channel ((p-channel macptr))
- "Sends #$flushCmd and #$quietCmd to P-CHANNEL."
- ;;
- (send-sound-command p-channel #$flushCmd 0 0 :immediate? t)
- (send-sound-command p-channel #$quietCmd 0 0 :immediate? t))
-
-
- (defmethod release-channel-if-*quietNotReleased* ((p-channel macptr))
- "Calls release-channel on P-CHANNEL if its state is *quietNotReleased*."
- ;;
- (let ((state (rref p-channel SndChannel.userInfo)))
- (when (= state *quietNotReleased*)
- (release-channel p-channel))))
-
-
- (defmethod quiet&release-channel ((p-channel macptr))
- "Calls flush&quiet-p-channel on P-CHANNEL if it is not in the *released*
- state, calls release-channel on it, then sets its userInfo field to
- *released*."
- ;;
- (let ((state (rref p-channel SndChannel.userInfo)))
- ;;
- ;; Check that STATE is valid. (This s/b a separate routine.)
- ;;
- (when (and (/= state *playing*)
- (/= state *quietNotReleased*)
- (/= state *released*))
- (error "~S is not one of these known states: ~S."
- state (list *released* *quietNotReleased* *playing*)))
- ;;
- ;; Quiet the channel if necessary.
- ;;
- (when (= state *playing*)
- (flush&quiet-p-channel p-channel))
- ;;
- ;; Release the channel and reset the userInfo flag (to show it's
- ;; *released*) if necessary.
- ;;
- (when (or (= state *playing*)
- (= state *quietNotReleased*))
- (release-channel p-channel))))
-
-
- (defmethod play-button-snd ((view sound-dialog)
- (button-nick-name symbol))
- "Plays the sound corresponding to BUTTON-NICK-NAME by getting the item's
- dialog-item-text and using it to play a sounds on one of the syths."
- ;;
- (let* ((snd-id (dialog-item-text (view-named button-nick-name view)))
- ;(h-sound (get-named-resource "snd " snd-id))
- (int-note-value (int-snd-id->note-value snd-id))
- (p-channel (nick-name->channel view button-nick-name)))
- ;(play-snd h-sound p-channel)
- (play-note int-note-value p-channel ;mc 2-Oct-91
- :square-wave? nil
- :int-table-length (int-table-length view)
- :ptr-table-data (ptr-table-data view)
- :int-amplitude 128)))
-
-
- (defmethod int-snd-id->note-value ((snd-id string)) ;mc 2-Oct-91
- "Returns the integer corresponding to snd-id that is the MIDI note value
- to play."
- ;;
- (let ((alist-id/note-pairs '(("Got an IV started" . 60) ;middle c
- ("Trouble with the IV" . 62) ;d
- ("Got The Tube In" . 64) ;e
- ("Trouble with the Tube" . 65) ;f
- )))
- (or (cdr (assoc snd-id alist-id/note-pairs :test #'string-equal))
- (error "~S not in ~S." snd-id alist-id/note-pairs))))
-
-
- (defmethod play-note ((int-note-value fixnum) (p-channel macptr)
- &key (square-wave? t) int-table-length ptr-table-data
- (int-amplitude 128))
- "Plays in p-channel the note indicated by int-note-value. First calls
- quiet&release-channel in case it's in *quietNotReleased* or *playing*. If
- square-wave? is non-nil then uses the #$squareWaveSynth. Otherwise, uses the
- #$waveTableSynth and a square wave. Int-table-length and ptr-table-data
- specify the wave table. Int-amplitude is an integer between 0 and 255
- inclusive."
- ;;
- (quiet&release-channel p-channel)
- ;;
- ;; Since #_SndNewChannel expects a pointer to a pointer we must use a
- ;; %stack-block to store its address.
- ;;
- (%stack-block ((pp-chan 4))
- (%put-ptr pp-chan p-channel)
- (handle-error (#_SndNewChannel pp-chan (if square-wave?
- #$squareWaveSynth #$waveTableSynth)
- #$initMono ;0 0 breaks here!
- *snd-call-back-ptr*)))
- ;;
- (rset p-channel SndChannel.userInfo *playing*) ;set to *quietNotReleased* by *snd-call-back-ptr*
- (unless square-wave? ;install the wave table first if necessary
- (send-sound-command p-channel #$waveTableCmd int-table-length
- (%ptr-to-int ptr-table-data)))
- ;;
- ;; Problem: #$ampCmd does nothing for #$waveTableSynth !!
- ;;
- (send-sound-command p-channel #$ampCmd int-amplitude 0)
- ;(%stack-block ((p-int-volume 4)) ;note: s/b doing something like this!
- ; (#_GetSoundVol p-int-volume)
- ; (%get-word p-int-volume))
- ;
- ;(#_SetSoundVol (round (* int-amplitude 7) 255)) ;slows it down a bit
- (send-sound-command p-channel #$freqDurationCmd
- 500 int-note-value) ;500 = 1/4 sec
- ;(send-sound-command p-channel #$quietCmd 0 0) ;required for #$freqDurationCmd
- (send-sound-command p-channel #$callBackCmd 0 0))
-
-
- (defmethod play-snd ((h-sound macptr) ;there is no machandle class, right?
- (p-channel macptr))
- "Plays in P-CHANNEL the sound pointed to by H-SOUND. First calls
- quiet&release-channel in case it's in *quietNotReleased* or *playing*."
- ;;
- (quiet&release-channel p-channel)
- ;;
- ;; Since #_SndNewChannel expects a pointer to a pointer we must use a
- ;; %stack-block to store its address.
- ;;
- (%stack-block ((pp-chan 4))
- (%put-ptr pp-chan p-channel)
- (handle-error (#_SndNewChannel pp-chan #$sampledSynth #$initMono ;0 0 breaks here!
- *snd-call-back-ptr*)))
- ;;
- (rset p-channel SndChannel.userInfo *playing*) ;set to *quietNotReleased* by *snd-call-back-ptr*
- (handle-error (#_SndPlay p-channel h-sound t)) ;async!
- (send-sound-command p-channel #$callBackCmd 0 0))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Define functions to print nice SoundManager error messages.
- ;;;
-
- (defclass error-entry ()
- ((error-name
- :accessor error-name
- :initarg :error-name
- :type string)
- (error-number
- :accessor error-number
- :initarg :error-number
- :type fixnum)
- (error-description
- :accessor error-description
- :initarg :error-description
- :type string)
- )
- (:documentation "Stores error information as imported from the InsideMac
- stacks."))
-
-
- (defmethod print-object ((object error-entry) stream)
- "Prints OBJECT with its components."
- ;;
- (print-unreadable-object (object stream :type t :identity t)
- (cond ((and (slot-boundp object 'error-name)
- (slot-boundp object 'error-number))
- (format stream "~A ~A" (error-name object) (error-number object)))
- (t
- (princ "??" stream)))))
-
-
- (defmethod parse-hypercard-error-list ((error-list string))
- "Returns as list of error-entries sorted in descending error-number
- order. ERROR-LIST is a string of lines; each line is of the form:
- '<error-name> <error-number> <error-description>
-
- and each item is separated by spaces."
- ;;
- (with-input-from-string (stream (substitute #\- #\– error-list))
- (let ((num-lines (count #\Return error-list))
- (error-list ()) ;form: list of (name value descr)
- line error-name-start error-name-end error-name
- error-number-start error-number-end error-number
- error-descr-start error-descr-end error-descr)
- (dotimes (line-num num-lines)
- (setf line (read-line stream)
- error-name-start 0
- error-name-end (position #\Space line :start error-name-start)
- error-name (subseq line error-name-start error-name-end)
- error-number-start
- (position-if-not #'(lambda (char) (char-equal char #\Space))
- line :start error-name-end)
- error-number-end (position #\Space line :start error-number-start)
- error-number (read-from-string (subseq line error-number-start error-number-end))
- error-descr-start
- (position-if-not #'(lambda (char) (char-equal char #\Space))
- line :start error-number-end)
- error-descr-end (length line)
- error-descr (subseq line error-descr-start error-descr-end))
- (push (make-instance
- 'error-entry :error-name error-name
- :error-number error-number
- :error-description error-descr)
- error-list))
- error-list)))
-
-
- (defvar *sound-manager-errors*
- (parse-hypercard-error-list
- "noErr 0 No error
- noHardwareErr –200 Required sound hardware not available
- notEnoughHardwareErr –201 Insufficient hardware available
- queueFull –203 No room in the queue
- resProblem –204 Problem loading the resource
- badChannel –205 Channel is corrupt or unusable
- badFormat –206 Resource is corrupt or unusable
- notEnoughBufferSpace –207 Insufficient memory available
- badFileFormat –208 File is corrupt or unusable, or not AIFF or AIFF-C
- channelBusy –209 Channel is busy
- buffersTooSmall –210 Buffer is too small
- channelNotBusy –211 Channel not currently used
- noMoreRealTime –212 Not enough CPU time available
- siNoSoundInHardware –220 No sound input hardware available
- siBadSoundInDevice –221 Invalid sound input device
- siNoBufferSpecified –222 No buffer specified
- siInvalidCompression –223 Invalid compression type
- siHardDriveTooSlow –224 Hard drive too slow to record
- siInvalidSampleRate –225 Invalid sample rate
- siInvalidSampleSize –226 Invalid sample size
- siDeviceBusyErr –227 Sound input device is busy
- siBadDeviceName –228 Invalid device name
- siBadRefNum –229 Invalid reference number
- siInputDeviceErr –230 Input device hardware failure
- siUnknownInfoType –231 Unknown type of information
- siUnknownQuality –232 Unknown quality")
- "A list of error-entries sorted as returned by
- parse-hypercard-error-list.")
-
-
- (defmethod error-code->error-entry ((error-code fixnum))
- "Returns the error-entry in *sound-manager-errors* corresponding to
- ERROR-CODE or nil if none found."
- ;;
- (find error-code *sound-manager-errors* :test #'= :key #'error-number))
-
-
- (defmethod handle-error ((error-code fixnum))
- "The top-level function for handling Sound Manager errors."
- ;;
- (unless (zerop error-code)
- (let ((error-entry (error-code->error-entry error-code)))
- (error "Sound Manager error (~S): ~A." error-code
- (if error-entry (error-description error-entry) "Unknown")))))
-
-
- #|
-
- (make-instance 'sound-dialog)
-
- |#
-